home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / BLWCB15A.ZIP / BFISHCBC.PAS < prev    next >
Pascal/Delphi Source File  |  1996-08-27  |  10KB  |  331 lines

  1. {$D+}
  2. unit BfishCBC;
  3.  
  4.   {*****************************************************************}
  5.   {*******   CBC Implementation of the BlowFish algorithm    *******}
  6.   {*******        Hereby donated to the public domain        *******}
  7.   {*****************************************************************}
  8.   {*******  BFISH in CBC (c)1996 by Dutra Lacerda <2:362/20> *******}
  9.   {*******   E-Mail address:  dutra.lacerda@mail.telepac.pt  *******}
  10.   {*******     Compuserve  :  100342,2501  (a month delay)   *******}
  11.   {*****************************************************************}
  12.  
  13. interface
  14.  
  15. uses BFish4, Dos;
  16.  
  17. const
  18.   Debug      = FALSE;
  19.   BufferSize = 8192;
  20.   BlockSize  = 8;
  21.   HalfSize   = 4;
  22.   Version    = 15;
  23.  
  24. procedure BLW_CBC_INIT(var k : String; N : Integer);
  25. procedure BLW_CBC_CRYPT(var InputFile : String; var OutputFile : String);
  26. procedure BLW_CBC_DECRYPT(var InputFile : String; var OutputFile : String);
  27.  
  28.  
  29. implementation
  30.  
  31.  
  32. var
  33.   VersionL : LongInt; {Value in EOF Header}
  34.   VersionC : Array[0..3] of Char ABSOLUTE VersionL;
  35.   VersionB : Array[0..3] of Byte ABSOLUTE VersionL;
  36.  
  37.   Key : String[56];
  38.   InputFile,
  39.   OutputFile : PathStr;
  40.   Argument : String[2];
  41.   Teller,
  42.   FillBuffer,
  43.   NumRead,
  44.   NumWritten : Word; { MUST be global }
  45.   Input,             { MUST be global }
  46.   Output : file;     { MUST be global }
  47.   Buffer : array[0..BufferSize-1] of LongInt;
  48.   FileVersion,
  49.   FileOrigSize,
  50.   InputSize,
  51.   Counter,
  52.   CBCinit,
  53.   CBC_l0,
  54.   CBC_r0,
  55.   CBC_l,
  56.   CBC_r,
  57.   _CBC_l,
  58.   _CBC_r : LongInt;
  59.   Pad_B : Array[0..15] OF byte;
  60.   Pad_L : Array[0..3] OF LongInt ABSOLUTE Pad_B;
  61.   Buf : Byte absolute Buffer;
  62.   P : PArray;
  63.   S : SBox;
  64.   PP : array[0..17, 0..3] of Byte absolute P;
  65.   SS : array[0..3, 0..255, 0..3] of Byte absolute S;
  66.   BB : array[0..(HalfSize*BufferSize)-1] of Byte absolute Buffer;
  67.   NIteract,
  68.   NBlocks,
  69.   NHalfs,
  70.   NPadBytes,
  71.   IOerror,
  72.   i : Integer;
  73.  
  74.   Fpath : Pathstr;
  75.   Fdir  : DirStr;
  76.   Fname : NameStr;
  77.   Fext  : ExtStr;
  78.  
  79.  
  80.   Procedure Create_CBC_IV( Init:LongInt; VAR Tl:LongInt; VAR Tr:LongInt );
  81.   const
  82.     DebugNum = $AAAAAAAA;
  83.   var
  84.     T    : Array[0..3] OF byte ABSOLUTE Tl;
  85.     Regs : Registers;
  86.   begin
  87.     If not Debug then
  88.        begin
  89.        Regs.AH := $2C;
  90.        MsDos(Regs);
  91.        with Regs do   { The order is not significant, choosed to put the }
  92.          begin        { most variable data alternated with the less one. }
  93.          T[0] := CH;  { Hour   }
  94.          T[1] := DL;  { Hundreds of second }
  95.          T[2] := CL;  { Minute }
  96.          T[3] := DH;  { Second }
  97.          end;         { NOTICE that T alters T1 }
  98.        Tl := Tl xor not DebugNum;
  99.        Tr := Init xor DebugNum;
  100.        end
  101.     else
  102.        Begin
  103.        Tl := DebugNum;
  104.        Tr := DebugNum;
  105.        end;
  106.   end;
  107.  
  108.   function CheckDisk: Boolean;
  109.   begin
  110.     if NumWritten=0 then
  111.       begin
  112.       Writeln;
  113.       Writeln( #13, #10, 'Unable to write Disk: Check for Disk Full...' );
  114.       close(input);
  115.       close(output);
  116.       halt(101);
  117.       end;
  118.   end;
  119.  
  120.   function CheckIO: integer;
  121.   var IOerror : integer;
  122.   begin
  123.     IOError := IOresult;
  124.     if IOError<>0 then
  125.       begin
  126.       ErrorAddr := NIL;
  127.       ExitCode  := 0;
  128.       Writeln( #13,#10, 'Please correct the problem and try again...' );
  129.       end;
  130.     CheckIO := IOerror;
  131.   end;
  132.  
  133.   function Passes(InputSize : LongInt) : LongInt;
  134.   begin
  135.     Passes := ((InputSize div (BufferSize*4))+
  136.                (InputSize mod (BufferSize*4))*1-
  137.                ((InputSize mod (BufferSize*4))*1-1));
  138.   end;
  139.  
  140.   procedure BLW_CBC_INIT(var k : String; N : Integer);
  141.   begin
  142.     Key := k;
  143.     NIteract := N;
  144.     InitBlowFish(Key, P, S);
  145.   end;
  146.  
  147.   procedure BLW_CBC_CRYPT(var InputFile : String; var OutputFile : String);
  148.   begin
  149.     Assign(Input, InputFile);
  150.     FileMode := 0; { 0= Read; 1=Write; 2=Read/Write}
  151.     {$I-} Reset(Input, 1); {$I+} IOerror := CheckIO;
  152.     If IOerror <> 0 then
  153.       begin
  154.       halt(IOerror);
  155.       end;
  156.     InputSize := FileSize(Input);
  157.  
  158.     Fpath := FExpand( InputFile );
  159.     FSplit(Fpath, Fdir, Fname, Fext);
  160.  
  161.     VersionB[0] := Version;
  162.     for i := 1 to 3 do
  163.       if (i > ord(Fext[0])) then
  164.         Fext[i] := #32;
  165.     for i := 1 to 3 do
  166.       VersionC[i] := Fext[i+1];
  167.  
  168.     if OutputFile = '' then
  169.       OutputFile := Fname+'.BFC';
  170.     Assign(Output, OutputFile);
  171.     FileMode := 1; { 0= Read; 1=Write; 2=Read/Write}
  172.     {$I-} Rewrite(Output, 1); {$I+} IOerror:=CheckIO;
  173.     If IOerror <> 0 then
  174.       begin
  175.       close(input);
  176.       halt(IOerror);
  177.       end;
  178.  
  179.     { Initialization of the CBC Mode Initial Vector }
  180.     GetFtime(Input, CBCinit);
  181.     Create_CBC_IV(CBCinit, CBC_l0, CBC_r0);
  182.     CBC_l  := CBC_l0;
  183.     CBC_r  := CBC_r0;
  184.  
  185.     NPadBytes := 0;               {Will be used only once}
  186.     NBlocks := BufferSize div BlockSize;
  187.     for Counter := 1 to Passes(InputSize) do
  188.       begin
  189.         if Counter = Passes(InputSize) then {Last Pass}
  190.           begin
  191.             FillBuffer := InputSize-((Passes(InputSize)-1)*(BufferSize*4));
  192.             NBlocks    := (FillBuffer+BlockSize-1) div BlockSize;
  193.             NPadBytes  := BlockSize-(FillBuffer mod BlockSize);
  194.             NHalfs     := 2*NBlocks;
  195.           end                     {IF-else Counter...}
  196.         else
  197.           begin
  198.             NHalfs := BufferSize;
  199.           end;                    {if-Else Counter...}
  200.  
  201.         BlockRead(Input, Buffer, SizeOf(Buffer), NumRead);
  202.  
  203.         (* Padding *)
  204.         Pad_L[0] := CBC_l0;
  205.         Pad_L[0] := not CBC_l0;
  206.         Pad_L[0] := CBC_r0;
  207.         Pad_L[0] := not CBC_r0;
  208.         if NPadBytes <> 0 then
  209.           begin
  210.             for i := 0 to NPadBytes-1 do
  211.               begin
  212.                 BB[FillBuffer+i] := Pad_B[ NPadBytes - i ];
  213.               end;                {for i...}
  214.           end;                    {if Npad..}
  215.  
  216.         Teller := 0;
  217.         While Teller <= (NHalfs-1) do
  218.           begin
  219.             Buffer[Teller]   := CBC_l xor Buffer[Teller];
  220.             Buffer[Teller+1] := CBC_r xor Buffer[Teller+1];
  221.             BlowEncrypt(Buffer[Teller], Buffer[Teller+1], P, S);
  222.             CBC_l := Buffer[Teller];
  223.             CBC_r := Buffer[Teller+1];
  224.             Inc(Teller);
  225.             Inc(Teller);
  226.           end;
  227.         BlockWrite(Output, Buffer, NumRead+NPadBytes, NumWritten);
  228.         Write('Pass ', Counter, ' of ');
  229.         Write((InputSize div (BufferSize*4))+1, '     ', #13);
  230.         CheckDisk;
  231.       end;                        {FOR}
  232.     WriteLn;
  233.     CBC_l := 1;
  234.     BlockWrite(Output, CBC_l0, SizeOf(CBC_l0), NumWritten);
  235.     CheckDisk;
  236.     BlockWrite(Output, CBC_r0, SizeOf(CBC_r0), NumWritten);
  237.     CheckDisk;
  238.     BlockWrite(Output, VersionL, SizeOf(VersionL), NumWritten);
  239.     CheckDisk;
  240.     BlockWrite(Output, InputSize, SizeOf(InputSize), NumWritten);
  241.     CheckDisk;
  242.     Close(Input);
  243.     Close(Output);
  244.   end;
  245.  
  246.  
  247.  
  248.   procedure BLW_CBC_DECRYPT(var InputFile : String; var OutputFile : String);
  249.   begin
  250.     Assign(Input, InputFile);
  251.     FileMode := 0; { 0= Read; 1=Write; 2=Read/Write}
  252.     {$I-} Reset(Input, 1); {$I+} IOerror := CheckIO;
  253.     If IOerror <> 0 then
  254.       begin
  255.       halt(IOerror);
  256.       end;
  257.     InputSize := FileSize(Input);
  258.  
  259.     Fpath := FExpand( InputFile );
  260.     FSplit(Fpath, Fdir, Fname, Fext);
  261.  
  262.     Seek(Input, FileSize(Input)-16);
  263.     BlockRead(Input, Buffer, SizeOf(Buffer), NumRead);
  264.     CBC_l := Buffer[0];
  265.     CBC_r := Buffer[1];
  266.     VersionL  := Buffer[2];
  267.     FileOrigSize := Buffer[3];
  268.  
  269.     if NOT (VersionB[0] = Version) then
  270.       begin
  271.       Write('Wrong version. File was Encrypted with version ');
  272.       Case VersionB[0] of
  273.         1  : WriteLn('1.3');
  274.         15 : WriteLn('1.5');
  275.         else
  276.            WriteLn('???');
  277.         end;
  278.       halt(254);
  279.       end;
  280.  
  281.     FileMode := 0; { 0= Read; 1=Write; 2=Read/Write}
  282.     Reset(Input, 1);
  283.     Fext := '.'+VersionC[1]+VersionC[2]+VersionC[3];
  284.     if OutputFile = '' then
  285.       OutputFile:= Fname+Fext;
  286.     Assign(Output, OutputFile);
  287.     FileMode := 1; { 0= Read; 1=Write; 2=Read/Write}
  288.     {$I-} Rewrite(Output, 1); {$I+} IOerror:=CheckIO;
  289.     If IOerror <> 0 then
  290.       begin
  291.       close(input);
  292.       halt(IOerror);
  293.       end;
  294.  
  295.     FillBuffer := BufferSize*4;
  296.     for Counter := 1 to Passes(InputSize) do
  297.       begin
  298.         if Counter = Passes(InputSize) then
  299.           begin
  300.             FillBuffer := InputSize-((Passes(InputSize)-1)*(BufferSize*4));
  301.           end;                    {if counter...}
  302.         BlockRead(Input, Buffer, SizeOf(Buffer), NumRead);
  303.         Teller := 0;
  304.         While Teller <= ((FillBuffer div 4)-1) do
  305.           begin
  306.             _CBC_l := Buffer[Teller];
  307.             _CBC_r := Buffer[Teller+1];
  308.             BlowDecrypt(Buffer[Teller], Buffer[Teller+1], P, S);
  309.             Buffer[Teller]   := Buffer[Teller] xor CBC_l;
  310.             Buffer[Teller+1] := Buffer[Teller+1] xor CBC_r;
  311.             CBC_l := _CBC_l;
  312.             CBC_r := _CBC_r;
  313.             Inc(Teller);
  314.             Inc(Teller);
  315.           end;                    {FOR}
  316.         BlockWrite(Output, Buffer, NumRead, NumWritten);
  317.         Write('Pass ', Counter, ' of ');
  318.         Write((InputSize div (BufferSize*4))+1, '     ', #13);
  319.         CheckDisk;
  320.       end;                        {FOR}
  321.     WriteLn;
  322.     Seek(Output, FileOrigSize);
  323.     Truncate(Output);
  324.     Close(Input);
  325.     Close(Output);
  326.   end;
  327.  
  328. begin
  329. end.
  330. {$D-}
  331.